/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
/**
* Basic field class
* $Log: Field.java,v $
* Revision 1.1.1.1  2004/04/22 12:56:14  travisb
* Fir
*
* Revision 1.1.1.1  2003/12/21 09:04:08  jaspervdb
* no message
*
* Revision 1.1.1.1  2003/10/20 15:30:48  travisb
* First import into CVS at Cellstop
*
* Revision 1.1.1.1  2003/03/30 15:25:28  tbulford
* no message
*
* Revision 1.1  2003/01/12 08:30:34  travis
* Import x MANY
*
* Revision 1.1.1.1  2002/12/16 22:14:01  jasper
* no message
*
* Revision 1.2  2002/05/02 14:36:06  JasperV
* Commiter: NPPS Pins finished except for loading of MTN and CellC Pins
*
* Revision 1.1  2002/02/20 13:30:43  JasperV
* First time add to new Applications layer
*
* Revision 1.2  2002/02/12 16:57:14  JasperV
* Updated version
*
* Revision 1.1  2002/01/24 14:18:14  travisb
* First Version of the Application Layer
*
* Revision 1.1  2002/01/21 08:06:07  travisb
* First version commited to CVS
*
*/

package blueprint4j.messages;

import java.io.*;
import java.util.*;
import java.text.*;

abstract public class Field {
	protected byte[] value = null;
	private int fieldsize;
	private int fieldsize_type;
	protected int field_position;
	String name;
	static private int system_audit_num = 10000;
	static private SimpleDateFormat field_12_format = new SimpleDateFormat("hhmmss");
	static private SimpleDateFormat field_13_format = new SimpleDateFormat("MMdd");

	/**
	* Defines the field
	* @param p_fieldsize_type
	* The way the size of the field is stored in 8583 must be one of the
	* following LENGTH_FIXED,LENGTH_LVAR,LENGTH_LLVAR or LENGTH_LLLVAR
	* @param p_fieldsize
	* this is the maximun size allows or the fixed length. Fields must
	* not exceed this size even if they are of a type that has a size header
	*/
	Field( int p_fieldsize_type, int p_fieldsize, int p_field_position, String _name )
	throws ExceptionMessage {
		name = _name;
		fieldsize = p_fieldsize;
		fieldsize_type = p_fieldsize_type;
		field_position = p_field_position;
		// Check field size type
		if ( fieldsize_type < 0 || fieldsize_type > LENGTH_TYPE_MAX ) {
			throw new ExceptionMessage( "Field Size Type given is not valid" );
		}
	}

	public String getName() {
		return name;
	}

	public int getFieldNumber() {
		return field_position;
	}

	final void read( InputStream input )
	throws ExceptionMessage , IOException {
		int fielduse = 0;
		if ( fieldsize_type == LENGTH_FIXED ) {
			fielduse = fieldsize;
		} else {
			int fhl = 0;
			switch ( fieldsize_type ) {
			case LENGTH_LVAR: fhl = 1;break;
			case LENGTH_LLVAR: fhl = 2;break;
			case LENGTH_LLLVAR: fhl = 3;break;
			case LENGTH_LLLLVAR: fhl = 4;break;
			case LENGTH_LLLLLVAR: fhl = 5;break;
			case LENGTH_LLLLLLVAR: fhl = 6;break;
			default: throw new ExceptionMessage( "Field Size Type given is not valid for field " + field_position );
			}
			try {
				fielduse = Integer.parseInt( Utils.readString( input, fhl ) );
			} catch ( NumberFormatException e ) {
				throw new ExceptionMessage( "Bad format for header for field " + field_position );
			}
		}
		set( Utils.readBytes( input, fielduse ) );
	}

	void set(byte buf[])
	throws ExceptionMessage {
		if (buf.length>fieldsize) {
			throw new ExceptionMessage("Field data being set is too long ["+buf.length+"] only expecting ["+fieldsize+"]");
		}
		set(new String(buf));
	}

	String getFieldValueDefault() {
		Date d = new Date();

		switch (field_position) {
		case 11:
			return "" + system_audit_num++;
		case 12:
			return field_12_format.format(d);
		case 13:
			return field_13_format.format(d);
		case 120:
			return field_12_format.format(d) + field_13_format.format(d) + system_audit_num++;
		}
		return "";
	}

	final void write( OutputStream output )
	throws ExceptionMessage , IOException {
		// Save is there is a value
		if ( !isNull() ) {
			int size = fieldsize;
			// Write header
			if ( fieldsize_type != LENGTH_FIXED ) {
				int fhl = 0;
				switch ( fieldsize_type ) {
				case LENGTH_LVAR: fhl = 1;break;
				case LENGTH_LLVAR: fhl = 2;break;
				case LENGTH_LLLVAR: fhl = 3;break;
				case LENGTH_LLLLVAR: fhl = 4;break;
				case LENGTH_LLLLLVAR: fhl = 5;break;
				case LENGTH_LLLLLLVAR: fhl = 6;break;
				default: throw new ExceptionMessage( "Field Size Type given is not valid for field " + field_position );
				}
				//size = get().length();
				size = getLength();
				String slength = "" + size;
				while ( slength.length() < fhl ) {
					slength = "0" + slength;
				}
				Utils.writeString( output, slength );
			}
			output.write( getPadded( size ) );
		}
	}

	protected int getLength()
	throws ExceptionMessage {
		return get().length();
	}

	final String get() {
		if (value != null) {
			return new String(value);
		}
		return null;
	}

	public byte[] getBytes()
	throws ExceptionMessage {
		return value;
	}

	public boolean isNull()
	throws ExceptionMessage {
		return get() == null;
	}

	void set( String p_value )
	throws ExceptionMessage {
		if ( p_value != null ) {
			if (p_value.length()>fieldsize) {
				throw new ExceptionMessage("Field data being set is too long ["+p_value.length()+"] only expecting ["+fieldsize+"]");
			}
			verify( p_value );
			value = p_value.getBytes();
		} else {
			value = null;
		}
	}

	void setBinary( byte p_value[] )
	throws ExceptionMessage {
		value = p_value;
	}

	int getFieldSize() {
		return fieldsize;
	}

	// Abstract methods
	abstract void verify( String value ) throws ExceptionMessage;
	abstract byte[] getPadded( int length ) throws ExceptionMessage;


	// Field type modifiers
	public final static int LENGTH_FIXED = 0;
	public final static int LENGTH_LVAR = 1;
	public final static int LENGTH_LLVAR = 2;
	public final static int LENGTH_LLLVAR = 3;
	public final static int LENGTH_LLLLVAR = 4;
	public final static int LENGTH_LLLLLVAR = 5;
	public final static int LENGTH_LLLLLLVAR = 6;
	final static int LENGTH_TYPE_MAX = 6;
}

